<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    // js一般数据类型存储
    // js引用数据类型存储

    //浅拷贝?
    /*
            浅拷贝是创建一个新对象 这个对象有着原始对象属性值的一份精确拷贝  
    如果属性值是-基本类型 拷贝的就是基本类型的值 
    如果属性值是-引用类型 拷贝的就是内存地址
    所以如果其中一个对象改变了地址 就会影响到另一个对象 
    */

    //深拷贝？
      //深拷贝是将一个对象从内存中完整的拷贝出来一份 从堆内存中开辟一个新的区域存放新的对象 且修改新对象 不会影响原对象 

    //赋值-浅拷贝-深拷贝区别？
    /*  浅拷贝和赋值的区别？ 
            当我们把一个对象赋值给一个新的变量时赋的其实时该对象的在栈中的地址  而不是堆中的数据  因此两个对象是联动的 
        浅拷贝？
            重新在堆中创建内存 拷贝前后对象的基本数据类型互不影响 但拷贝前后对象的引用类型共享一块内存 会相互的影响
        深拷贝？
            从堆中内存开辟一个新的区域存放对象 对对象中的子对象进行递归拷贝 拷贝前后的两个对象互不影响        
    */

    /*
        浅拷贝的实现方式 ?
            Object.assign 
            ...拓展运算符
            Array.prototype.concat
            Array.prototype.slice 
            lodash里面的_.clone
        深拷贝的实现方式？
            JSON.pares(JSON.stringify())
            递归操作
            $.extends 

    */

    //赋值 
         var person = {                              
             name:"平安喜乐",                         //普通类型
             hobby:["学习",["看书","shoping"],"跑步"] //引用数据类型 
         }   
         var person1 = person;   //这步把一个对象赋值给了一个变量person1 赋的是栈中的地址 而不是堆中的数据 因此两个对象是联动的(即会影响)   
         person1.name = "收购腾讯";
         person1.hobby[0] = "沙发瘫";
         console.log(person)     // {name: "收购腾讯", hobby: Array(3)}hobby: (3) ["沙发瘫", Array(2), "跑步"]name: "收购腾讯"__proto__: Object
         console.log(person1)    // {name: "收购腾讯", hobby: Array(3)}hobby: (3) ["沙发瘫", Array(2), "跑步"]name: "收购腾讯"__proto__: Object


    //浅拷贝
         var p = {                              
             name:"平安喜乐",                         //普通类型String
             hobby:["学习",["看书","shoping"],"跑步"] //引用数据类型  Object
         }
         function shallowCopy(obj){
             var target = {}        //重新在堆中创建内存 
            for(var i in obj){
             if(obj.hasOwnProperty(i)){
                 target[i] = obj[i]
             }
            }
             return target
         }
         var person1 = shallowCopy(p) //把上面p这个对象传进来
         person1.name = "收购腾讯";          //拷贝前后对象的基本数据类型互不影响 person平安喜乐 person1收购腾讯
         person1.hobby[0] = "沙发瘫";        //拷贝前后对象的引用类型共享一块内存 会相互的影响 联动 都变成了沙发瘫
         console.log(p)                     //name: "平安喜乐",  ["沙发瘫", Array(2), "跑步"] 
         console.log(person1)               //name: "收购腾讯",  ["沙发瘫", Array(2), "跑步"] 


//深拷贝 
    var person = {                              
        name:"平安喜乐",                         //普通类型String
        hobby:["学习",["看书","shoping"],"跑步"], //引用数据类型  Object
        fn:function(){},
        reg:new RegExp("\\w+")
    }
    function deepClone(obj){
                                                          //加出口判断 
        if(typeof obj !=="object") return obj              //判断传入的objxx..是不是对象 
        if(obj === null) return obj                        //遗留bug null空对象
        if(obj instanceof Date) return new Date(obj)       //时间
        if(obj instanceof RegExp) return new RegExp(obj)   //正则
 
        var cloneObj = {}                                 //重新在堆中创建内存
        for (var i in obj){
            if(obj.hasOwnProperty(i)){
                cloneObj[i] = deepClone(obj[i])  //再次调用把obj[i]传入 调用函数自己 
            }
        }
        return cloneObj
    }
    var person1 = deepClone(person)                  //使用递归深拷贝


    // var person1 = JSON.parse(JSON.stringify(person))    //使用JSON.parse(JSON.stringify()) 实现深拷贝     
                                                           //有缺点的 如果属性是个函数、正则、时间 
    person1.name = "收购腾讯";         
    person1.hobby[0] = "沙发瘫";       
    console.log(person)    // name: "平安喜乐"    hobby: (3) ["学习", Array(2), "跑步"]
    console.log(person1)   // name: "收购腾讯",   hobby: {0: "沙发瘫", 1: {…}, 2: "跑步"}







</script>